﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using OwnZTec.Common;
using OwnZTec.Dto;
using OwnZTec.DbCommon;

namespace OwnZTec.Da
{
    public class DaUsuario : IDaLeitura<DtoUsuario>, IDaEscrita<DtoUsuario>
    {
        #region -- Mapeamento -------------------------------------------------------------------------------------------------------------
        internal static Mapeamento<DtoUsuario> Mapear = delegate(IDataReader dr, DtoUsuario obj)
        {
            obj.Id = Utils.ParaInteiro(dr["idUsuario"]);
            obj.Nome = Utils.ParaString(dr["desNome"]);
            obj.Login = Utils.ParaString(dr["desLogin"]);
            obj.Senha = "";
            obj.Email = Utils.ParaString(dr["desEmail"]);
            obj.Notas = Utils.ParaString(dr["desNotas"]);
            obj.MudarSenha = Utils.ParaBool(dr["flgMudarSenha"]);

            obj.Perfil = new DtoPerfil();
            DaPerfil.Mapear(dr, obj.Perfil);
        };
        #endregion ------------------------------------------------------------------------------------------------------------------------

        #region -- Membros e Construtores -------------------------------------------------------------------------------------------------
        private const string SenhaPadrao = "Jownz&2011C";
        #endregion ------------------------------------------------------------------------------------------------------------------------

        #region -- Metodos de Leitura -----------------------------------------------------------------------------------------------------
        public List<DtoUsuario> ListarTodos()
        {
            var db = new DbCommon.DbCommon
            {
                TipoComando = CommandType.StoredProcedure,
                Comando = "uspUsuarioListarTodos"
            };

            return db.ExecutarLista(Mapear);
        }

        public DtoUsuario ListarUm(int id)
        {
            var db = new DbCommon.DbCommon
            {
                TipoComando = CommandType.StoredProcedure,
                Comando = "uspUsuarioListarUm"
            };

            db.Parametros.Add(db.CriarParametro("Id", id, ParameterDirection.Input));

            return db.ExecutarObjeto(Mapear);
        }

        public int ValidarUsuario(DtoUsuario usuario)
        {
            try
            {
                var db = new DbCommon.DbCommon
                {
                    TipoComando = CommandType.StoredProcedure,
                    Comando = "uspUsuarioValidar"
                };

                var ok = -1;

                db.Parametros.Add(db.CriarParametro("Login", usuario.Login, 50, ParameterDirection.Input));
                db.Parametros.Add(db.CriarParametro("Senha", Seguranca.Hash(usuario.Senha), 50, ParameterDirection.Input));
                db.Parametros.Add(db.CriarParametro("Id", ok, ParameterDirection.Output));

                db.ExecutarSemRetorno();

                ok = (int)db.Parametros.Where(p => p.ParameterName == "@Id").First().Value;

                return ok;
            }
            catch
            {
                return -1;
            }
        }

        public bool ValidarUsuarioSenhaPadrao(DtoUsuario usuario)
        {
            try
            {
                var db = new DbCommon.DbCommon
                {
                    TipoComando = CommandType.StoredProcedure,
                    Comando = "uspUsuarioValidar"
                };

                var ok = false;

                db.Parametros.Add(db.CriarParametro("Login", usuario.Login, 50, ParameterDirection.Input));
                db.Parametros.Add(db.CriarParametro("Senha", Seguranca.Hash(SenhaPadrao), 50, ParameterDirection.Input));
                db.Parametros.Add(db.CriarParametro("Status", ok, ParameterDirection.Output));

                db.ExecutarSemRetorno();

                ok = (bool)db.Parametros.Where(p => p.ParameterName == "@Status").First().Value;

                return ok;
            }
            catch
            {
                return false;
            }
        }
        public bool LoginExiste(string login, int id = 0)
        {
            try
            {
                var db = new DbCommon.DbCommon
                {
                    TipoComando = CommandType.StoredProcedure,
                    Comando = "uspUsuarioLoginExiste"
                };

                var ok = false;

                db.Parametros.Add(db.CriarParametro("Login", login, ParameterDirection.Input));
                db.Parametros.Add(db.CriarParametro("Id", id, ParameterDirection.Input));
                db.Parametros.Add(db.CriarParametro("Status", ok, ParameterDirection.Output));

                db.ExecutarSemRetorno();

                ok = (bool)db.Parametros.Where(p => p.ParameterName == "@Status").First().Value;

                return ok;
            }
            catch
            {
                return false;
            }
        }
        #endregion ------------------------------------------------------------------------------------------------------------------------

        #region -- Metodos de Escrita -----------------------------------------------------------------------------------------------------
        public bool Salvar(DtoUsuario usuario)
        {
            return usuario.Id == 0 ? CriarUsuario(usuario) : AtualizarUsuario(usuario);
        }

        private static bool AtualizarUsuario(DtoUsuario usuario)
        {
            try
            {
                var db = new DbCommon.DbCommon
                {
                    TipoComando = CommandType.StoredProcedure,
                    Comando = "uspUsuarioAlterar"
                };

                db.Parametros.Add(db.CriarParametro("Id", usuario.Id, ParameterDirection.Input));
                db.Parametros.Add(db.CriarParametro("Nome", usuario.Nome, 50, ParameterDirection.Input));
                db.Parametros.Add(db.CriarParametro("IdPerfil", usuario.Perfil.Id, ParameterDirection.Input));
                db.Parametros.Add(db.CriarParametro("Login", usuario.Login, 50, ParameterDirection.Input));
                db.Parametros.Add(db.CriarParametro("Email", usuario.Email, 50, ParameterDirection.Input));
                db.Parametros.Add(db.CriarParametro("Notas", usuario.Notas, 100, ParameterDirection.Input));

                db.ExecutarSemRetorno();

                return true;
            }
            catch
            {
                return false;
            }
        }

        private static bool CriarUsuario(DtoUsuario usuario)
        {
            try
            {
                var db = new DbCommon.DbCommon
                             {
                                 TipoComando = CommandType.StoredProcedure,
                                 Comando = "uspUsuarioCriar"
                             };

                db.Parametros.Add(db.CriarParametro("Nome", usuario.Nome, 50, ParameterDirection.Input));
                db.Parametros.Add(db.CriarParametro("Login", usuario.Login, 50, ParameterDirection.Input));
                db.Parametros.Add(db.CriarParametro("Senha", Seguranca.Hash(SenhaPadrao), 100, ParameterDirection.Input));
                db.Parametros.Add(db.CriarParametro("Notas", usuario.Notas, 100, ParameterDirection.Input));
                db.Parametros.Add(db.CriarParametro("Email", usuario.Email, 50, ParameterDirection.Input));
                db.Parametros.Add(db.CriarParametro("idPerfil", usuario.Perfil.Id, ParameterDirection.Input));

                db.Parametros.Add(db.CriarParametro("Id", usuario.Id, ParameterDirection.Output));

                db.ExecutarSemRetorno();

                usuario.Id = (int)db.Parametros.Where(p => p.ParameterName == "@Id").First().Value;

                return true;
            }
            catch
            {
                return false;
            }
        }

        public bool AtualizarSenha(DtoUsuario usuario)
        {
            try
            {
                var db = new DbCommon.DbCommon
                {
                    TipoComando = CommandType.StoredProcedure,
                    Comando = "uspUsuarioAlterarSenha"
                };

                db.Parametros.Add(db.CriarParametro("Id", usuario.Id, ParameterDirection.Input));
                db.Parametros.Add(db.CriarParametro("Senha", Seguranca.Hash(usuario.Senha), 100, ParameterDirection.Input));

                db.ExecutarSemRetorno();

                return true;
            }
            catch
            {
                return false;
            }
        }

        public bool ResetarSenha(DtoUsuario usuario)
        {
            try
            {
                var db = new DbCommon.DbCommon
                {
                    TipoComando = CommandType.StoredProcedure,
                    Comando = "uspUsuarioAlterarSenha"
                };

                db.Parametros.Add(db.CriarParametro("Id", usuario.Id, ParameterDirection.Input));
                db.Parametros.Add(db.CriarParametro("Senha", Seguranca.Hash(SenhaPadrao), 100, ParameterDirection.Input));
                db.Parametros.Add(db.CriarParametro("MudarSenha", 1, ParameterDirection.Input));

                db.ExecutarSemRetorno();

                return true;
            }
            catch
            {
                return false;
            }
        }

        public bool Excluir(int id)
        {
            try
            {
                var db = new DbCommon.DbCommon
                {
                    TipoComando = CommandType.StoredProcedure,
                    Comando = "uspUsuarioExcluir"
                };

                db.Parametros.Add(db.CriarParametro("Id", id, ParameterDirection.Input));

                db.ExecutarSemRetorno();

                return true;
            }
            catch
            {
                return false;
            }
        }

        public bool ExcluirTodos()
        {
            throw new NotImplementedException();
        }
        #endregion ------------------------------------------------------------------------------------------------------------------------
    }
}
